package com.mask.token.service;

import com.mask.token.model.TokenInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.Instant;

/**
 * Token刷新策略
 * 提供不同的Token刷新策略
 *
 * @author mask
 * @since 1.0.0
 */
@Slf4j
@Component
public class MaskTokenRefreshStrategy {

    /**
     * 默认刷新策略：基于时间阈值
     *
     * @param tokenInfo Token信息
     * @param threshold 刷新阈值
     * @return 是否需要刷新
     */
    public boolean shouldRefreshByTime(TokenInfo tokenInfo, Duration threshold) {
        if (tokenInfo == null) {
            return false;
        }

        Instant now = Instant.now();
        Instant refreshTime = tokenInfo.getExpireTime().minus(threshold);
        
        boolean shouldRefresh = now.isAfter(refreshTime);
        log.debug("Token刷新检查 - 当前时间: {}, 刷新时间: {}, 需要刷新: {}", 
                now, refreshTime, shouldRefresh);
        
        return shouldRefresh;
    }

    /**
     * 基于活跃度的刷新策略
     * 如果用户最近活跃，则提前刷新Token
     *
     * @param tokenInfo Token信息
     * @param threshold 刷新阈值
     * @param activeThreshold 活跃度阈值
     * @return 是否需要刷新
     */
    public boolean shouldRefreshByActivity(TokenInfo tokenInfo, Duration threshold, Duration activeThreshold) {
        if (tokenInfo == null) {
            return false;
        }

        Instant now = Instant.now();
        Instant lastActiveTime = tokenInfo.getLastActiveTime();
        
        // 如果用户最近活跃，使用更短的刷新阈值
        Duration effectiveThreshold = threshold;
        if (lastActiveTime != null && Duration.between(lastActiveTime, now).compareTo(activeThreshold) < 0) {
            effectiveThreshold = threshold.dividedBy(2); // 活跃用户提前刷新
            log.debug("用户活跃，使用更短的刷新阈值: {}", effectiveThreshold);
        }
        
        return shouldRefreshByTime(tokenInfo, effectiveThreshold);
    }

    /**
     * 基于使用频率的刷新策略
     * 根据Token使用频率决定刷新策略
     *
     * @param tokenInfo Token信息
     * @param threshold 基础刷新阈值
     * @param usageCount 使用次数
     * @param maxUsageCount 最大使用次数
     * @return 是否需要刷新
     */
    public boolean shouldRefreshByUsage(TokenInfo tokenInfo, Duration threshold, int usageCount, int maxUsageCount) {
        if (tokenInfo == null) {
            return false;
        }

        // 如果使用次数接近最大值，提前刷新
        if (usageCount >= maxUsageCount * 0.8) {
            Duration earlyThreshold = threshold.multipliedBy(2); // 提前刷新
            log.debug("Token使用频繁，提前刷新，使用次数: {}/{}", usageCount, maxUsageCount);
            return shouldRefreshByTime(tokenInfo, earlyThreshold);
        }
        
        return shouldRefreshByTime(tokenInfo, threshold);
    }

    /**
     * 智能刷新策略
     * 综合多种因素决定是否刷新
     *
     * @param tokenInfo Token信息
     * @param threshold 基础刷新阈值
     * @param activeThreshold 活跃度阈值
     * @param usageCount 使用次数
     * @param maxUsageCount 最大使用次数
     * @return 是否需要刷新
     */
    public boolean shouldRefreshIntelligently(TokenInfo tokenInfo, Duration threshold, 
                                            Duration activeThreshold, int usageCount, int maxUsageCount) {
        if (tokenInfo == null) {
            return false;
        }

        // 检查基础时间条件
        boolean timeBased = shouldRefreshByTime(tokenInfo, threshold);
        
        // 检查活跃度条件
        boolean activityBased = shouldRefreshByActivity(tokenInfo, threshold, activeThreshold);
        
        // 检查使用频率条件
        boolean usageBased = shouldRefreshByUsage(tokenInfo, threshold, usageCount, maxUsageCount);
        
        // 综合判断：满足任一条件即可刷新
        boolean shouldRefresh = timeBased || activityBased || usageBased;
        
        log.debug("智能刷新检查 - 时间: {}, 活跃度: {}, 使用频率: {}, 最终结果: {}", 
                timeBased, activityBased, usageBased, shouldRefresh);
        
        return shouldRefresh;
    }

    /**
     * 计算刷新后的Token有效期
     * 根据当前Token状态动态调整有效期
     *
     * @param tokenInfo 当前Token信息
     * @param baseValidity 基础有效期
     * @return 建议的有效期
     */
    public Duration calculateRefreshValidity(TokenInfo tokenInfo, Duration baseValidity) {
        if (tokenInfo == null) {
            return baseValidity;
        }

        Duration validity = baseValidity;
        
        // 如果用户最近活跃，延长有效期
        Instant now = Instant.now();
        Instant lastActiveTime = tokenInfo.getLastActiveTime();
        
        if (lastActiveTime != null && Duration.between(lastActiveTime, now).compareTo(Duration.ofMinutes(30)) < 0) {
            validity = validity.multipliedBy(2); // 活跃用户延长有效期
            log.debug("用户活跃，延长Token有效期: {}", validity);
        }
        
        return validity;
    }
}
